using Identity.Application.Contracts.Common;
using Identity.Application.Contracts.Services;
using Identity.Infrastructure.Entities;
using Microsoft.AspNetCore.Identity;

namespace Identity.Infrastructure.Persistence.IdentityService;

public class UserRoleService : IUserRoleService
{
    private readonly UserManager<ApplicationUser> _userManager;

    private readonly RoleManager<ApplicationRole> _roleManager;

    public UserRoleService(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
    {
        _userManager = userManager;
        _roleManager = roleManager;
    }

    public async Task<OperationResult> AssignRoleAsync(Guid userId, Guid roleId)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return OperationResult.Failed("User not found");

        var role = await _roleManager.FindByIdAsync(roleId.ToString());
        if (role == null) return OperationResult.Failed("role not found");

        var result = await _userManager.AddToRoleAsync(user, role.Name!);
        return result.Succeeded ? OperationResult.Success() : OperationResult.Failed(string.Join(",", result.Errors.Select(e => e.Description)));
    }

    public async Task<OperationResult> RemoveRoleAsync(Guid userId, Guid roleId)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return OperationResult.Failed("User not found");

        var role = await _roleManager.FindByIdAsync(roleId.ToString());
        if (role == null) return OperationResult.Failed("role not found");

        var result = await _userManager.RemoveFromRoleAsync(user, role.Name!);
        return result.Succeeded ? OperationResult.Success() : OperationResult.Failed(string.Join(",", result.Errors.Select(e => e.Description)));
    }

    public async Task<IList<string>> GetUserRolesAsync(Guid userId)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return Array.Empty<string>();
        return await _userManager.GetRolesAsync(user);
    }

    public async Task<IList<UserDto>> GetUsersInRoleAsync(Guid roleId)
    {
        var role = await _roleManager.FindByIdAsync(roleId.ToString());
        if (role == null) return Array.Empty<UserDto>();
        var users = await _userManager.GetUsersInRoleAsync(role.Name!);


        var userDatas = users.Select(async u => new UserDto(u.Id, u.UserName!, u.Email!, await _userManager.GetRolesAsync(u)));

        var userList = await Task.WhenAll(userDatas);

        return userList.ToList();

    }

    public async Task<bool> AddRolesAsync(Guid userId, List<Guid> RoleIds)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return false;

        var roles = await Task.WhenAll(
            RoleIds.Select(id => _roleManager.FindByIdAsync(id.ToString()))
        );

        // 过滤掉找不到的角色
        var validRoles = roles.Where(r => r != null).ToList();
        if (!validRoles.Any()) return false;

        // 获取角色名
        var roleNames = validRoles
            .Select(r => r!.Name) // Role对象本身就有Name属性，没必要再GetRoleNameAsync
            .Where(name => !string.IsNullOrWhiteSpace(name))
            .ToList();

        if (!roleNames.Any()) return false;

        // 批量添加角色
        var result = await _userManager.AddToRolesAsync(user, roleNames);
        return result.Succeeded;
    }

    public async Task<bool> ReplaceRolesAsync(Guid userId, List<Guid> newRoleIds)
    {
        var user = await _userManager.FindByIdAsync(userId.ToString());
        if (user == null) return false;

        // 1. 获取用户当前的角色
        var currentRoles = await _userManager.GetRolesAsync(user);

        // 2. 删除用户的所有旧角色
        if (currentRoles.Any())
            await _userManager.RemoveFromRolesAsync(user, currentRoles);

        // 3. 根据 newRoleIds 查找新角色的名称
        var newRoles = await Task.WhenAll(
            newRoleIds.Select(async r => await _roleManager.FindByIdAsync(r.ToString()))
        );

        var newRoleNames = await Task.WhenAll(
            newRoles.Select(async r => await _roleManager.GetRoleNameAsync(r!))
        );

        // 4. 添加新角色
        await _userManager.AddToRolesAsync(user, newRoleNames);

        return true;
    }
}